home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 February (DVD) / PCWorld_2008-02_DVD.iso / v cisle / PHP / PHP.exe / xampp-win32-1.6.5-installer.exe / phpMyAdmin / libraries / database_interface.lib.php < prev    next >
Encoding:
PHP Script  |  2007-12-20  |  48.1 KB  |  1,289 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  * Common Option Constants For DBI Functions
  5.  *
  6.  * @version $Id: database_interface.lib.php 10732 2007-10-06 20:03:52Z lem9 $
  7.  */
  8.  
  9. /**
  10.  *
  11.  */
  12. // PMA_DBI_try_query()
  13. define('PMA_DBI_QUERY_STORE',       1);  // Force STORE_RESULT method, ignored by classic MySQL.
  14. define('PMA_DBI_QUERY_UNBUFFERED',  2);  // Do not read whole query
  15. // PMA_DBI_get_variable()
  16. define('PMA_DBI_GETVAR_SESSION', 1);
  17. define('PMA_DBI_GETVAR_GLOBAL', 2);
  18.  
  19. /**
  20.  * Loads the mysql extensions if it is not loaded yet
  21.  *
  22.  * @param   string  $extension  mysql extension to load
  23.  */
  24. function PMA_DBI_checkAndLoadMysqlExtension($extension = 'mysql') {
  25.     if (! function_exists($extension . '_connect')) {
  26.         PMA_dl($extension);
  27.         // check whether mysql is available
  28.         if (! function_exists($extension . '_connect')) {
  29.             return false;
  30.         }
  31.     }
  32.  
  33.     return true;
  34. }
  35.  
  36.  
  37. /**
  38.  * check for requested extension
  39.  */
  40. if (! PMA_DBI_checkAndLoadMysqlExtension($GLOBALS['cfg']['Server']['extension'])) {
  41.  
  42.     // if it fails try alternative extension ...
  43.     // and display an error ...
  44.  
  45.     /**
  46.      * @todo 2.7.1: add different messages for alternativ extension
  47.      * and complete fail (no alternativ extension too)
  48.      */
  49.     $GLOBALS['PMA_errors'][] =
  50.         sprintf(PMA_sanitize($GLOBALS['strCantLoad']),
  51.             $GLOBALS['cfg']['Server']['extension'])
  52.         .' - <a href="./Documentation.html#faqmysql" target="documentation">'
  53.         .$GLOBALS['strDocu'] . '</a>';
  54.  
  55.     if ($GLOBALS['cfg']['Server']['extension'] === 'mysql') {
  56.         $alternativ_extension = 'mysqli';
  57.     } else {
  58.         $alternativ_extension = 'mysql';
  59.     }
  60.  
  61.     if (! PMA_DBI_checkAndLoadMysqlExtension($alternativ_extension)) {
  62.         // if alternativ fails too ...
  63.         PMA_fatalError(
  64.             sprintf($GLOBALS['strCantLoad'],
  65.                 $GLOBALS['cfg']['Server']['extension'])
  66.             . ' - [a@./Documentation.html#faqmysql@documentation]'
  67.             . $GLOBALS['strDocu'] . '[/a]');
  68.     }
  69.  
  70.     $GLOBALS['cfg']['Server']['extension'] = $alternativ_extension;
  71.     unset($alternativ_extension);
  72. }
  73.  
  74. /**
  75.  * Including The DBI Plugin
  76.  */
  77. require_once './libraries/dbi/' . $GLOBALS['cfg']['Server']['extension'] . '.dbi.lib.php';
  78.  
  79. /**
  80.  * Common Functions
  81.  */
  82. function PMA_DBI_query($query, $link = null, $options = 0) {
  83.     $res = PMA_DBI_try_query($query, $link, $options)
  84.         or PMA_mysqlDie(PMA_DBI_getError($link), $query);
  85.     return $res;
  86. }
  87.  
  88. /**
  89.  * converts charset of a mysql message, usally coming from mysql_error(),
  90.  * into PMA charset, usally UTF-8
  91.  * uses language to charset mapping from mysql/share/errmsg.txt
  92.  * and charset names to ISO charset from information_schema.CHARACTER_SETS
  93.  *
  94.  * @uses    $GLOBALS['cfg']['IconvExtraParams']
  95.  * @uses    $GLOBALS['charset']     as target charset
  96.  * @uses    PMA_DBI_fetch_value()   to get server_language
  97.  * @uses    preg_match()            to filter server_language
  98.  * @uses    in_array()
  99.  * @uses    function_exists()       to check for a convert function
  100.  * @uses    iconv()                 to convert message
  101.  * @uses    libiconv()              to convert message
  102.  * @uses    recode_string()         to convert message
  103.  * @uses    mb_convert_encoding()   to convert message
  104.  * @param   string  $message
  105.  * @return  string  $message
  106.  */
  107. function PMA_DBI_convert_message($message) {
  108.     // latin always last!
  109.     $encodings = array(
  110.         'japanese'      => 'EUC-JP', //'ujis',
  111.         'japanese-sjis' => 'Shift-JIS', //'sjis',
  112.         'korean'        => 'EUC-KR', //'euckr',
  113.         'russian'       => 'KOI8-R', //'koi8r',
  114.         'ukrainian'     => 'KOI8-U', //'koi8u',
  115.         'greek'         => 'ISO-8859-7', //'greek',
  116.         'serbian'       => 'CP1250', //'cp1250',
  117.         'estonian'      => 'ISO-8859-13', //'latin7',
  118.         'slovak'        => 'ISO-8859-2', //'latin2',
  119.         'czech'         => 'ISO-8859-2', //'latin2',
  120.         'hungarian'     => 'ISO-8859-2', //'latin2',
  121.         'polish'        => 'ISO-8859-2', //'latin2',
  122.         'romanian'      => 'ISO-8859-2', //'latin2',
  123.         'spanish'       => 'CP1252', //'latin1',
  124.         'swedish'       => 'CP1252', //'latin1',
  125.         'italian'       => 'CP1252', //'latin1',
  126.         'norwegian-ny'  => 'CP1252', //'latin1',
  127.         'norwegian'     => 'CP1252', //'latin1',
  128.         'portuguese'    => 'CP1252', //'latin1',
  129.         'danish'        => 'CP1252', //'latin1',
  130.         'dutch'         => 'CP1252', //'latin1',
  131.         'english'       => 'CP1252', //'latin1',
  132.         'french'        => 'CP1252', //'latin1',
  133.         'german'        => 'CP1252', //'latin1',
  134.     );
  135.  
  136.     if ($server_language = PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'language\';', 0, 1)) {
  137.         $found = array();
  138.         if (preg_match('&(?:\\\|\\/)([^\\\\\/]*)(?:\\\|\\/)$&i', $server_language, $found)) {
  139.             $server_language = $found[1];
  140.         }
  141.     }
  142.  
  143.     if (! empty($server_language) && isset($encodings[$server_language])) {
  144.         if (function_exists('iconv')) {
  145.             if ((@stristr(PHP_OS, 'AIX')) && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) {
  146.                 require_once './libraries/iconv_wrapper.lib.php';
  147.                 $message = PMA_aix_iconv_wrapper($encodings[$server_language],
  148.                     $GLOBALS['charset'] . $GLOBALS['cfg']['IconvExtraParams'], $message);
  149.             } else {
  150.                 $message = iconv($encodings[$server_language],
  151.                     $GLOBALS['charset'] . $GLOBALS['cfg']['IconvExtraParams'], $message);
  152.             }
  153.         } elseif (function_exists('recode_string')) {
  154.             $message = recode_string($encodings[$server_language] . '..'  . $GLOBALS['charset'],
  155.                 $message);
  156.         } elseif (function_exists('libiconv')) {
  157.             $message = libiconv($encodings[$server_language], $GLOBALS['charset'], $message);
  158.         } elseif (function_exists('mb_convert_encoding')) {
  159.             // do not try unsupported charsets
  160.             if (! in_array($server_language, array('ukrainian', 'greek', 'serbian'))) {
  161.                 $message = mb_convert_encoding($message, $GLOBALS['charset'],
  162.                     $encodings[$server_language]);
  163.             }
  164.         }
  165.     } else {
  166.         /**
  167.          * @todo lang not found, try all, what TODO ?
  168.          */
  169.     }
  170.  
  171.     return $message;
  172. }
  173.  
  174. /**
  175.  * returns array with table names for given db
  176.  *
  177.  * @param   string  $database   name of database
  178.  * @param   mixed   $link       mysql link resource|object
  179.  * @return  array   tables names
  180.  */
  181. function PMA_DBI_get_tables($database, $link = null)
  182. {
  183.     return PMA_DBI_fetch_result('SHOW TABLES FROM ' . PMA_backquote($database) . ';',
  184.         null, 0, $link, PMA_DBI_QUERY_STORE);
  185. }
  186.  
  187. /**
  188.  * returns array of all tables in given db or dbs
  189.  * this function expects unqoted names:
  190.  * RIGHT: my_database
  191.  * WRONG: `my_database`
  192.  * WRONG: my\_database
  193.  * if $tbl_is_group is true, $table is used as filter for table names
  194.  * if $tbl_is_group is 'comment, $table is used as filter for table comments
  195.  *
  196.  * <code>
  197.  * PMA_DBI_get_tables_full('my_database');
  198.  * PMA_DBI_get_tables_full('my_database', 'my_table'));
  199.  * PMA_DBI_get_tables_full('my_database', 'my_tables_', true));
  200.  * PMA_DBI_get_tables_full('my_database', 'my_tables_', 'comment'));
  201.  * </code>
  202.  *
  203.  * @uses    PMA_MYSQL_INT_VERSION
  204.  * @uses    PMA_DBI_fetch_result()
  205.  * @uses    PMA_escape_mysql_wildcards()
  206.  * @uses    PMA_backquote()
  207.  * @uses    is_array()
  208.  * @uses    addslashes()
  209.  * @uses    strpos()
  210.  * @uses    strtoupper()
  211.  * @param   string          $databases      database
  212.  * @param   string          $table          table
  213.  * @param   boolean|string  $tbl_is_group   $table is a table group
  214.  * @param   resource        $link           mysql link
  215.  * @return  array           list of tables in given db(s)
  216.  */
  217. function PMA_DBI_get_tables_full($database, $table = false,
  218.     $tbl_is_group = false, $link = null, $limit_offset = 0, $limit_count = false)
  219. {
  220.     // currently supported for MySQL >= 50002
  221.     if (true === $limit_count) {
  222.         $limit_count = $GLOBALS['cfg']['MaxTableList'];
  223.     }
  224.     // prepare and check parameters
  225.     if (! is_array($database)) {
  226.         $databases = array($database);
  227.     } else {
  228.         $databases = $database;
  229.     }
  230.  
  231.     $tables = array();
  232.  
  233.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  234.         // get table information from information_schema
  235.         if ($table) {
  236.             if (true === $tbl_is_group) {
  237.                 $sql_where_table = 'AND `TABLE_NAME` LIKE \''
  238.                     . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  239.             } elseif ('comment' === $tbl_is_group) {
  240.                 $sql_where_table = 'AND `TABLE_COMMENT` LIKE \''
  241.                     . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  242.             } else {
  243.                 $sql_where_table = 'AND `TABLE_NAME` = \'' . addslashes($table) . '\'';
  244.             }
  245.         } else {
  246.             $sql_where_table = '';
  247.         }
  248.  
  249.         // for PMA bc:
  250.         // `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME`
  251.         //
  252.         // on non-Windows servers,
  253.         // added BINARY in the WHERE clause to force a case sensitive
  254.         // comparison (if we are looking for the db Aa we don't want
  255.         // to find the db aa)
  256.         $this_databases = array_map('PMA_sqlAddslashes', $databases);
  257.  
  258.         $sql = '
  259.              SELECT *,
  260.                     `TABLE_SCHEMA`       AS `Db`,
  261.                     `TABLE_NAME`         AS `Name`,
  262.                     `ENGINE`             AS `Engine`,
  263.                     `ENGINE`             AS `Type`,
  264.                     `VERSION`            AS `Version`,
  265.                     `ROW_FORMAT`         AS `Row_format`,
  266.                     `TABLE_ROWS`         AS `Rows`,
  267.                     `AVG_ROW_LENGTH`     AS `Avg_row_length`,
  268.                     `DATA_LENGTH`        AS `Data_length`,
  269.                     `MAX_DATA_LENGTH`    AS `Max_data_length`,
  270.                     `INDEX_LENGTH`       AS `Index_length`,
  271.                     `DATA_FREE`          AS `Data_free`,
  272.                     `AUTO_INCREMENT`     AS `Auto_increment`,
  273.                     `CREATE_TIME`        AS `Create_time`,
  274.                     `UPDATE_TIME`        AS `Update_time`,
  275.                     `CHECK_TIME`         AS `Check_time`,
  276.                     `TABLE_COLLATION`    AS `Collation`,
  277.                     `CHECKSUM`           AS `Checksum`,
  278.                     `CREATE_OPTIONS`     AS `Create_options`,
  279.                     `TABLE_COMMENT`      AS `Comment`
  280.                FROM `information_schema`.`TABLES`
  281.               WHERE ' . (PMA_IS_WINDOWS ? '' : 'BINARY') . ' `TABLE_SCHEMA` IN (\'' . implode("', '", $this_databases) . '\')
  282.                 ' . $sql_where_table;
  283.  
  284.         if ($limit_count) {
  285.             $sql .= ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
  286.         }
  287.         $tables = PMA_DBI_fetch_result($sql, array('TABLE_SCHEMA', 'TABLE_NAME'),
  288.             null, $link);
  289.         unset($sql_where_table, $sql);
  290.     }
  291.     // If permissions are wrong on even one database directory,
  292.     // information_schema does not return any table info for any database
  293.     // this is why we fall back to SHOW TABLE STATUS even for MySQL >= 50002
  294.     if (PMA_MYSQL_INT_VERSION < 50002 || empty($tables)) {
  295.         foreach ($databases as $each_database) {
  296.             if (true === $tbl_is_group) {
  297.                 $sql = 'SHOW TABLE STATUS FROM '
  298.                     . PMA_backquote($each_database)
  299.                     .' LIKE \'' . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  300.             } else {
  301.                 $sql = 'SHOW TABLE STATUS FROM '
  302.                     . PMA_backquote($each_database) . ';';
  303.             }
  304.             $each_tables = PMA_DBI_fetch_result($sql, 'Name', null, $link);
  305.             foreach ($each_tables as $table_name => $each_table) {
  306.                 if ('comment' === $tbl_is_group
  307.                   && 0 === strpos($each_table['Comment'], $table))
  308.                 {
  309.                     // remove table from list
  310.                     unset($each_tables[$table_name]);
  311.                     continue;
  312.                 }
  313.  
  314.                 if (! isset($each_tables[$table_name]['Type'])
  315.                   && isset($each_tables[$table_name]['Engine'])) {
  316.                     // pma BC, same parts of PMA still uses 'Type'
  317.                     $each_tables[$table_name]['Type']
  318.                         =& $each_tables[$table_name]['Engine'];
  319.                 } elseif (! isset($each_tables[$table_name]['Engine'])
  320.                   && isset($each_tables[$table_name]['Type'])) {
  321.                     // old MySQL reports Type, newer MySQL reports Engine
  322.                     $each_tables[$table_name]['Engine']
  323.                         =& $each_tables[$table_name]['Type'];
  324.                 }
  325.  
  326.                 // MySQL forward compatibility
  327.                 // so pma could use this array as if every server is of version >5.0
  328.                 $each_tables[$table_name]['TABLE_SCHEMA']      = $each_database;
  329.                 $each_tables[$table_name]['TABLE_NAME']        =& $each_tables[$table_name]['Name'];
  330.                 $each_tables[$table_name]['ENGINE']            =& $each_tables[$table_name]['Engine'];
  331.                 $each_tables[$table_name]['VERSION']           =& $each_tables[$table_name]['Version'];
  332.                 $each_tables[$table_name]['ROW_FORMAT']        =& $each_tables[$table_name]['Row_format'];
  333.                 $each_tables[$table_name]['TABLE_ROWS']        =& $each_tables[$table_name]['Rows'];
  334.                 $each_tables[$table_name]['AVG_ROW_LENGTH']    =& $each_tables[$table_name]['Avg_row_length'];
  335.                 $each_tables[$table_name]['DATA_LENGTH']       =& $each_tables[$table_name]['Data_length'];
  336.                 $each_tables[$table_name]['MAX_DATA_LENGTH']   =& $each_tables[$table_name]['Max_data_length'];
  337.                 $each_tables[$table_name]['INDEX_LENGTH']      =& $each_tables[$table_name]['Index_length'];
  338.                 $each_tables[$table_name]['DATA_FREE']         =& $each_tables[$table_name]['Data_free'];
  339.                 $each_tables[$table_name]['AUTO_INCREMENT']    =& $each_tables[$table_name]['Auto_increment'];
  340.                 $each_tables[$table_name]['CREATE_TIME']       =& $each_tables[$table_name]['Create_time'];
  341.                 $each_tables[$table_name]['UPDATE_TIME']       =& $each_tables[$table_name]['Update_time'];
  342.                 $each_tables[$table_name]['CHECK_TIME']        =& $each_tables[$table_name]['Check_time'];
  343.                 $each_tables[$table_name]['TABLE_COLLATION']   =& $each_tables[$table_name]['Collation'];
  344.                 $each_tables[$table_name]['CHECKSUM']          =& $each_tables[$table_name]['Checksum'];
  345.                 $each_tables[$table_name]['CREATE_OPTIONS']    =& $each_tables[$table_name]['Create_options'];
  346.                 $each_tables[$table_name]['TABLE_COMMENT']     =& $each_tables[$table_name]['Comment'];
  347.  
  348.                 if (strtoupper($each_tables[$table_name]['Comment']) === 'VIEW') {
  349.                     $each_tables[$table_name]['TABLE_TYPE'] = 'VIEW';
  350.                 } else {
  351.                     /**
  352.                      * @todo difference between 'TEMPORARY' and 'BASE TABLE' but how to detect?
  353.                      */
  354.                     $each_tables[$table_name]['TABLE_TYPE'] = 'BASE TABLE';
  355.                 }
  356.             }
  357.  
  358.             $tables[$each_database] = $each_tables;
  359.         }
  360.     }
  361.  
  362.     if ($GLOBALS['cfg']['NaturalOrder']) {
  363.         foreach ($tables as $key => $val) {
  364.             uksort($tables[$key], 'strnatcasecmp');
  365.         }
  366.     }
  367.  
  368.     if (! is_array($database)) {
  369.         if (isset($tables[$database])) {
  370.             return $tables[$database];
  371.         } elseif (isset($tables[strtolower($database)])) {
  372.             // on windows with lower_case_table_names = 1
  373.             // MySQL returns
  374.             // with SHOW DATABASES or information_schema.SCHEMATA: `Test`
  375.             // but information_schema.TABLES gives `test`
  376.             // bug #1436171
  377.             // http://sf.net/support/tracker.php?aid=1436171
  378.             return $tables[strtolower($database)];
  379.         } else {
  380.             return $tables;
  381.         }
  382.     } else {
  383.         return $tables;
  384.     }
  385. }
  386.  
  387. /**
  388.  * returns array with databases containing extended infos about them
  389.  *
  390.  * @todo    move into PMA_List_Database?
  391.  * @param   string      $databases      database
  392.  * @param   boolean     $force_stats    retrieve stats also for MySQL < 5
  393.  * @param   resource    $link           mysql link
  394.  * @param   string      $sort_by        collumn to order by
  395.  * @param   string      $sort_order     ASC or DESC
  396.  * @param   integer     $limit_offset   starting offset for LIMIT
  397.  * @param   bool|int    $limit_count    row count for LIMIT or true for $GLOBALS['cfg']['MaxDbList']
  398.  * @return  array       $databases
  399.  */
  400. function PMA_DBI_get_databases_full($database = null, $force_stats = false,
  401.     $link = null, $sort_by = 'SCHEMA_NAME', $sort_order = 'ASC',
  402.     $limit_offset = 0, $limit_count = false)
  403. {
  404.     $sort_order = strtoupper($sort_order);
  405.  
  406.     if (true === $limit_count) {
  407.         $limit_count = $GLOBALS['cfg']['MaxDbList'];
  408.     }
  409.  
  410.     // initialize to avoid errors when there are no databases
  411.     $databases = array();
  412.  
  413.     $apply_limit_and_order_manual = true;
  414.  
  415.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  416.         /**
  417.          * if $GLOBALS['cfg']['NaturalOrder'] is enabled, we cannot use LIMIT
  418.          * cause MySQL does not support natural ordering, we have to do it afterward
  419.          */
  420.         if ($GLOBALS['cfg']['NaturalOrder']) {
  421.             $limit = '';
  422.         } else {
  423.             if ($limit_count) {
  424.                 $limit = ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
  425.             }
  426.  
  427.             $apply_limit_and_order_manual = false;
  428.         }
  429.  
  430.         // get table information from information_schema
  431.         if ($database) {
  432.             $sql_where_schema = 'WHERE `SCHEMA_NAME` LIKE \''
  433.                 . addslashes($database) . '\'';
  434.         } else {
  435.             $sql_where_schema = '';
  436.         }
  437.  
  438.         // for PMA bc:
  439.         // `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME`
  440.         $sql = '
  441.              SELECT `information_schema`.`SCHEMATA`.*';
  442.         if ($force_stats) {
  443.             $sql .= ',
  444.                     COUNT(`information_schema`.`TABLES`.`TABLE_SCHEMA`)
  445.                         AS `SCHEMA_TABLES`,
  446.                     SUM(`information_schema`.`TABLES`.`TABLE_ROWS`)
  447.                         AS `SCHEMA_TABLE_ROWS`,
  448.                     SUM(`information_schema`.`TABLES`.`DATA_LENGTH`)
  449.                         AS `SCHEMA_DATA_LENGTH`,
  450.                     SUM(`information_schema`.`TABLES`.`MAX_DATA_LENGTH`)
  451.                         AS `SCHEMA_MAX_DATA_LENGTH`,
  452.                     SUM(`information_schema`.`TABLES`.`INDEX_LENGTH`)
  453.                         AS `SCHEMA_INDEX_LENGTH`,
  454.                     SUM(`information_schema`.`TABLES`.`DATA_LENGTH`
  455.                       + `information_schema`.`TABLES`.`INDEX_LENGTH`)
  456.                         AS `SCHEMA_LENGTH`,
  457.                     SUM(`information_schema`.`TABLES`.`DATA_FREE`)
  458.                         AS `SCHEMA_DATA_FREE`';
  459.         }
  460.         $sql .= '
  461.                FROM `information_schema`.`SCHEMATA`';
  462.         if ($force_stats) {
  463.             $sql .= '
  464.           LEFT JOIN `information_schema`.`TABLES`
  465.                  ON BINARY `information_schema`.`TABLES`.`TABLE_SCHEMA`
  466.                   = BINARY `information_schema`.`SCHEMATA`.`SCHEMA_NAME`';
  467.         }
  468.         $sql .= '
  469.               ' . $sql_where_schema . '
  470.            GROUP BY BINARY `information_schema`.`SCHEMATA`.`SCHEMA_NAME`
  471.            ORDER BY BINARY ' . PMA_backquote($sort_by) . ' ' . $sort_order
  472.            . $limit;
  473.         $databases = PMA_DBI_fetch_result($sql, 'SCHEMA_NAME', null, $link);
  474.  
  475.         $mysql_error = PMA_DBI_getError($link);
  476.         if (! count($databases) && $GLOBALS['errno']) {
  477.             PMA_mysqlDie($mysql_error, $sql);
  478.         }
  479.  
  480.         // display only databases also in official database list
  481.         // f.e. to apply hide_db and only_db
  482.         $drops = array_diff(array_keys($databases), $GLOBALS['PMA_List_Database']->items);
  483.         if (count($drops)) {
  484.             foreach ($drops as $drop) {
  485.                 unset($databases[$drop]);
  486.             }
  487.             unset($drop);
  488.         }
  489.         unset($sql_where_schema, $sql, $drops);
  490.     } else {
  491.         foreach ($GLOBALS['PMA_List_Database']->items as $database_name) {
  492.             // MySQL forward compatibility
  493.             // so pma could use this array as if every server is of version >5.0
  494.             $databases[$database_name]['SCHEMA_NAME']      = $database_name;
  495.  
  496.             if ($force_stats) {
  497.                 require_once 'mysql_charsets.lib.php';
  498.  
  499.                 $databases[$database_name]['DEFAULT_COLLATION_NAME']
  500.                     = PMA_getDbCollation($database_name);
  501.  
  502.                 // get additonal info about tables
  503.                 $databases[$database_name]['SCHEMA_TABLES']          = 0;
  504.                 $databases[$database_name]['SCHEMA_TABLE_ROWS']      = 0;
  505.                 $databases[$database_name]['SCHEMA_DATA_LENGTH']     = 0;
  506.                 $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH'] = 0;
  507.                 $databases[$database_name]['SCHEMA_INDEX_LENGTH']    = 0;
  508.                 $databases[$database_name]['SCHEMA_LENGTH']          = 0;
  509.                 $databases[$database_name]['SCHEMA_DATA_FREE']       = 0;
  510.  
  511.                 $res = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($database_name) . ';');
  512.                 while ($row = PMA_DBI_fetch_assoc($res)) {
  513.                     $databases[$database_name]['SCHEMA_TABLES']++;
  514.                     $databases[$database_name]['SCHEMA_TABLE_ROWS']
  515.                         += $row['Rows'];
  516.                     $databases[$database_name]['SCHEMA_DATA_LENGTH']
  517.                         += $row['Data_length'];
  518.                     $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH']
  519.                         += $row['Max_data_length'];
  520.                     $databases[$database_name]['SCHEMA_INDEX_LENGTH']
  521.                         += $row['Index_length'];
  522.                     $databases[$database_name]['SCHEMA_DATA_FREE']
  523.                         += $row['Data_free'];
  524.                     $databases[$database_name]['SCHEMA_LENGTH']
  525.                         += $row['Data_length'] + $row['Index_length'];
  526.                 }
  527.                 PMA_DBI_free_result($res);
  528.                 unset($res);
  529.             }
  530.         }
  531.     }
  532.  
  533.     /**
  534.      * apply limit and order manually now
  535.      * (caused by older MySQL < 5 or $GLOBALS['cfg']['NaturalOrder'])
  536.      */
  537.     if ($apply_limit_and_order_manual) {
  538.  
  539.         /**
  540.          * first apply ordering
  541.          */
  542.         if ($GLOBALS['cfg']['NaturalOrder']) {
  543.             $sorter = 'strnatcasecmp';
  544.         } else {
  545.             $sorter = 'strcasecmp';
  546.         }
  547.  
  548.         // produces f.e.:
  549.         // return -1 * strnatcasecmp($a["SCHEMA_TABLES"], $b["SCHEMA_TABLES"])
  550.         $sort_function = '
  551.             return ' . ($sort_order == 'ASC' ? 1 : -1) . ' * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
  552.         ';
  553.  
  554.         usort($databases, create_function('$a, $b', $sort_function));
  555.  
  556.         /**
  557.          * now apply limit
  558.          */
  559.         if ($limit_count) {
  560.             $databases = array_slice($databases, $limit_offset, $limit_count);
  561.         }
  562.     }
  563.  
  564.     return $databases;
  565. }
  566.  
  567. /**
  568.  * returns detailed array with all columns for given table in database,
  569.  * or all tables/databases
  570.  *
  571.  * @param   string  $database   name of database
  572.  * @param   string  $table      name of table to retrieve columns from
  573.  * @param   string  $column     name of specific column
  574.  * @param   mixed   $link       mysql link resource
  575.  */
  576. function PMA_DBI_get_columns_full($database = null, $table = null,
  577.     $column = null, $link = null)
  578. {
  579.     $columns = array();
  580.  
  581.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  582.         $sql_wheres = array();
  583.         $array_keys = array();
  584.  
  585.         // get columns information from information_schema
  586.         if (null !== $database) {
  587.             $sql_wheres[] = '`TABLE_SCHEMA` = \'' . addslashes($database) . '\' ';
  588.         } else {
  589.             $array_keys[] = 'TABLE_SCHEMA';
  590.         }
  591.         if (null !== $table) {
  592.             $sql_wheres[] = '`TABLE_NAME` = \'' . addslashes($table) . '\' ';
  593.         } else {
  594.             $array_keys[] = 'TABLE_NAME';
  595.         }
  596.         if (null !== $column) {
  597.             $sql_wheres[] = '`COLUMN_NAME` = \'' . addslashes($column) . '\' ';
  598.         } else {
  599.             $array_keys[] = 'COLUMN_NAME';
  600.         }
  601.  
  602.         // for PMA bc:
  603.         // `[SCHEMA_FIELD_NAME]` AS `[SHOW_FULL_COLUMNS_FIELD_NAME]`
  604.         $sql = '
  605.              SELECT *,
  606.                     `COLUMN_NAME`       AS `Field`,
  607.                     `COLUMN_TYPE`       AS `Type`,
  608.                     `COLLATION_NAME`    AS `Collation`,
  609.                     `IS_NULLABLE`       AS `Null`,
  610.                     `COLUMN_KEY`        AS `Key`,
  611.                     `COLUMN_DEFAULT`    AS `Default`,
  612.                     `EXTRA`             AS `Extra`,
  613.                     `PRIVILEGES`        AS `Privileges`,
  614.                     `COLUMN_COMMENT`    AS `Comment`
  615.                FROM `information_schema`.`COLUMNS`';
  616.         if (count($sql_wheres)) {
  617.             $sql .= "\n" . ' WHERE ' . implode(' AND ', $sql_wheres);
  618.         }
  619.  
  620.         $columns = PMA_DBI_fetch_result($sql, $array_keys, null, $link);
  621.         unset($sql_wheres, $sql);
  622.     } else {
  623.         if (null === $database) {
  624.             foreach ($GLOBALS['PMA_List_Database']->items as $database) {
  625.                 $columns[$database] = PMA_DBI_get_columns_full($database, null,
  626.                     null, $link);
  627.             }
  628.             return $columns;
  629.         } elseif (null === $table) {
  630.             $tables = PMA_DBI_get_tables($database);
  631.             foreach ($tables as $table) {
  632.                 $columns[$table] = PMA_DBI_get_columns_full(
  633.                     $database, $table, null, $link);
  634.             }
  635.             return $columns;
  636.         }
  637.  
  638.         $sql = 'SHOW FULL COLUMNS FROM '
  639.             . PMA_backquote($database) . '.' . PMA_backquote($table);
  640.         if (null !== $column) {
  641.             $sql .= " LIKE '" . $column . "'";
  642.         }
  643.  
  644.         $columns = PMA_DBI_fetch_result($sql, 'Field', null, $link);
  645.  
  646.         $ordinal_position = 1;
  647.         foreach ($columns as $column_name => $each_column) {
  648.  
  649.             // MySQL forward compatibility
  650.             // so pma could use this array as if every server is of version >5.0
  651.             $columns[$column_name]['COLUMN_NAME']                 =& $columns[$column_name]['Field'];
  652.             $columns[$column_name]['COLUMN_TYPE']                 =& $columns[$column_name]['Type'];
  653.             $columns[$column_name]['COLLATION_NAME']              =& $columns[$column_name]['Collation'];
  654.             $columns[$column_name]['IS_NULLABLE']                 =& $columns[$column_name]['Null'];
  655.             $columns[$column_name]['COLUMN_KEY']                  =& $columns[$column_name]['Key'];
  656.             $columns[$column_name]['COLUMN_DEFAULT']              =& $columns[$column_name]['Default'];
  657.             $columns[$column_name]['EXTRA']                       =& $columns[$column_name]['Extra'];
  658.             $columns[$column_name]['PRIVILEGES']                  =& $columns[$column_name]['Privileges'];
  659.             $columns[$column_name]['COLUMN_COMMENT']              =& $columns[$column_name]['Comment'];
  660.  
  661.             $columns[$column_name]['TABLE_CATALOG']               = null;
  662.             $columns[$column_name]['TABLE_SCHEMA']                = $database;
  663.             $columns[$column_name]['TABLE_NAME']                  = $table;
  664.             $columns[$column_name]['ORDINAL_POSITION']            = $ordinal_position;
  665.             $columns[$column_name]['DATA_TYPE']                   =
  666.                 substr($columns[$column_name]['COLUMN_TYPE'], 0,
  667.                     strpos($columns[$column_name]['COLUMN_TYPE'], '('));
  668.             /**
  669.              * @todo guess CHARACTER_MAXIMUM_LENGTH from COLUMN_TYPE
  670.              */
  671.             $columns[$column_name]['CHARACTER_MAXIMUM_LENGTH']    = null;
  672.             /**
  673.              * @todo guess CHARACTER_OCTET_LENGTH from CHARACTER_MAXIMUM_LENGTH
  674.              */
  675.             $columns[$column_name]['CHARACTER_OCTET_LENGTH']      = null;
  676.             $columns[$column_name]['NUMERIC_PRECISION']           = null;
  677.             $columns[$column_name]['NUMERIC_SCALE']               = null;
  678.             $columns[$column_name]['CHARACTER_SET_NAME']          =
  679.                 substr($columns[$column_name]['COLLATION_NAME'], 0,
  680.                     strpos($columns[$column_name]['COLLATION_NAME'], '_'));
  681.  
  682.             $ordinal_position++;
  683.         }
  684.  
  685.         if (null !== $column) {
  686.             reset($columns);
  687.             $columns = current($columns);
  688.         }
  689.     }
  690.  
  691.     return $columns;
  692. }
  693.  
  694. /**
  695.  * @todo should only return columns names, for more info use PMA_DBI_get_columns_full()
  696.  *
  697.  * @deprecated by PMA_DBI_get_columns() or PMA_DBI_get_columns_full()
  698.  * @param   string  $database   name of database
  699.  * @param   string  $table      name of table to retrieve columns from
  700.  * @param   mixed   $link       mysql link resource
  701.  * @return  array   column info
  702.  */
  703. function PMA_DBI_get_fields($database, $table, $link = null)
  704. {
  705.     // here we use a try_query because when coming from
  706.     // tbl_create + tbl_properties.inc.php, the table does not exist
  707.     $fields = PMA_DBI_fetch_result(
  708.         'SHOW FULL COLUMNS
  709.         FROM ' . PMA_backquote($database) . '.' . PMA_backquote($table),
  710.         null, null, $link);
  711.     if (! is_array($fields) || count($fields) < 1) {
  712.         return false;
  713.     }
  714.     return $fields;
  715. }
  716.  
  717. /**
  718.  * array PMA_DBI_get_columns(string $database, string $table, bool $full = false, mysql db link $link = null)
  719.  *
  720.  * @param   string  $database   name of database
  721.  * @param   string  $table      name of table to retrieve columns from
  722.  * @param   boolean $full       wether to return full info or only column names
  723.  * @param   mixed   $link       mysql link resource
  724.  * @return  array   column names
  725.  */
  726. function PMA_DBI_get_columns($database, $table, $full = false, $link = null)
  727. {
  728.     $fields = PMA_DBI_fetch_result(
  729.         'SHOW ' . ($full ? 'FULL' : '') . ' COLUMNS
  730.         FROM ' . PMA_backquote($database) . '.' . PMA_backquote($table),
  731.         'Field', ($full ? null : 'Field'), $link);
  732.     if (! is_array($fields) || count($fields) < 1) {
  733.         return false;
  734.     }
  735.     return $fields;
  736. }
  737.  
  738. /**
  739.  * returns value of given mysql server variable
  740.  *
  741.  * @param   string  $var    mysql server variable name
  742.  * @param   int     $type   PMA_DBI_GETVAR_SESSION|PMA_DBI_GETVAR_GLOBAL
  743.  * @param   mixed   $link   mysql link resource|object
  744.  * @return  mixed   value for mysql server variable
  745.  */
  746. function PMA_DBI_get_variable($var, $type = PMA_DBI_GETVAR_SESSION, $link = null)
  747. {
  748.     if ($link === null) {
  749.         if (isset($GLOBALS['userlink'])) {
  750.             $link = $GLOBALS['userlink'];
  751.         } else {
  752.             return false;
  753.         }
  754.     }
  755.     if (PMA_MYSQL_INT_VERSION < 40002) {
  756.         $type = 0;
  757.     }
  758.     switch ($type) {
  759.         case PMA_DBI_GETVAR_SESSION:
  760.             $modifier = ' SESSION';
  761.             break;
  762.         case PMA_DBI_GETVAR_GLOBAL:
  763.             $modifier = ' GLOBAL';
  764.             break;
  765.         default:
  766.             $modifier = '';
  767.     }
  768.     return PMA_DBI_fetch_value(
  769.         'SHOW' . $modifier . ' VARIABLES LIKE \'' . $var . '\';', 0, 1, $link);
  770. }
  771.  
  772. /**
  773.  * @uses    ./libraries/charset_conversion.lib.php
  774.  * @uses    PMA_DBI_QUERY_STORE
  775.  * @uses    PMA_REMOVED_NON_UTF_8
  776.  * @uses    PMA_MYSQL_INT_VERSION
  777.  * @uses    PMA_MYSQL_STR_VERSION
  778.  * @uses    PMA_DBI_GETVAR_SESSION
  779.  * @uses    PMA_DBI_fetch_value()
  780.  * @uses    PMA_DBI_query()
  781.  * @uses    PMA_DBI_get_variable()
  782.  * @uses    $GLOBALS['collation_connection']
  783.  * @uses    $GLOBALS['charset_connection']
  784.  * @uses    $GLOBALS['available_languages']
  785.  * @uses    $GLOBALS['mysql_charset_map']
  786.  * @uses    $GLOBALS['charset']
  787.  * @uses    $GLOBALS['lang']
  788.  * @uses    $GLOBALS['cfg']['Lang']
  789.  * @uses    $GLOBALS['cfg']['ColumnTypes']
  790.  * @uses    defined()
  791.  * @uses    explode()
  792.  * @uses    sprintf()
  793.  * @uses    intval()
  794.  * @uses    define()
  795.  * @uses    defined()
  796.  * @uses    substr()
  797.  * @uses    count()
  798.  * @param   mixed   $link   mysql link resource|object
  799.  * @param   boolean $is_controluser
  800.  */
  801. function PMA_DBI_postConnect($link, $is_controluser = false)
  802. {
  803.     if (!defined('PMA_MYSQL_INT_VERSION')) {
  804.         $mysql_version = PMA_DBI_fetch_value(
  805.             'SELECT VERSION()', 0, 0, $link, PMA_DBI_QUERY_STORE);
  806.         if ($mysql_version) {
  807.             $match = explode('.', $mysql_version);
  808.             define('PMA_MYSQL_INT_VERSION',
  809.                 (int) sprintf('%d%02d%02d', $match[0], $match[1],
  810.                         intval($match[2])));
  811.             define('PMA_MYSQL_STR_VERSION', $mysql_version);
  812.             unset($mysql_version, $match);
  813.         } else {
  814.             define('PMA_MYSQL_INT_VERSION', 32332);
  815.             define('PMA_MYSQL_STR_VERSION', '3.23.32');
  816.         }
  817.     }
  818.  
  819.     if (!defined('PMA_ENGINE_KEYWORD')) {
  820.         if (PMA_MYSQL_INT_VERSION >= 40102) {
  821.             define('PMA_ENGINE_KEYWORD','ENGINE');
  822.         } else {
  823.             define('PMA_ENGINE_KEYWORD','TYPE');
  824.         }
  825.     }
  826.  
  827.     if (PMA_MYSQL_INT_VERSION >= 40100) {
  828.  
  829.         // If $lang is defined and we are on MySQL >= 4.1.x,
  830.         // we auto-switch the lang to its UTF-8 version (if it exists and user
  831.         // didn't force language)
  832.         if (!empty($GLOBALS['lang'])
  833.           && (substr($GLOBALS['lang'], -5) != 'utf-8')
  834.           && !isset($GLOBALS['cfg']['Lang'])) {
  835.             $lang_utf_8_version =
  836.                 substr($GLOBALS['lang'], 0, strpos($GLOBALS['lang'], '-'))
  837.                 . '-utf-8';
  838.             if (!empty($GLOBALS['available_languages'][$lang_utf_8_version])) {
  839.                 $GLOBALS['lang'] = $lang_utf_8_version;
  840.                 $GLOBALS['charset'] = 'utf-8';
  841.                 define('PMA_LANG_RELOAD', 1);
  842.             }
  843.         }
  844.  
  845.         // and we remove the non-UTF-8 choices to avoid confusion
  846.         if (!defined('PMA_REMOVED_NON_UTF_8')) {
  847.             foreach ($GLOBALS['available_languages'] as $each_lang => $dummy) {
  848.                 if (substr($each_lang, -5) != 'utf-8') {
  849.                     unset($GLOBALS['available_languages'][$each_lang]);
  850.                 }
  851.             }
  852.             define('PMA_REMOVED_NON_UTF_8', 1);
  853.         }
  854.  
  855.         $mysql_charset = $GLOBALS['mysql_charset_map'][$GLOBALS['charset']];
  856.         if ($is_controluser
  857.           || empty($GLOBALS['collation_connection'])
  858.           || (strpos($GLOBALS['collation_connection'], '_')
  859.                 ? substr($GLOBALS['collation_connection'], 0, strpos($GLOBALS['collation_connection'], '_'))
  860.                 : $GLOBALS['collation_connection']) == $mysql_charset) {
  861.  
  862.             PMA_DBI_query('SET NAMES ' . $mysql_charset . ';', $link,
  863.                 PMA_DBI_QUERY_STORE);
  864.         } else {
  865.             PMA_DBI_query('SET CHARACTER SET ' . $mysql_charset . ';', $link,
  866.                 PMA_DBI_QUERY_STORE);
  867.         }
  868.         if (!empty($GLOBALS['collation_connection'])) {
  869.             PMA_DBI_query('SET collation_connection = \'' . $GLOBALS['collation_connection'] . '\';',
  870.                 $link, PMA_DBI_QUERY_STORE);
  871.         }
  872.         if (!$is_controluser) {
  873.             $GLOBALS['collation_connection'] = PMA_DBI_get_variable('collation_connection',
  874.                 PMA_DBI_GETVAR_SESSION, $link);
  875.             $GLOBALS['charset_connection']   = PMA_DBI_get_variable('character_set_connection',
  876.                 PMA_DBI_GETVAR_SESSION, $link);
  877.         }
  878.  
  879.         // Add some field types to the list, this needs to be done once per session!
  880.         if (!in_array('BINARY', $GLOBALS['cfg']['ColumnTypes'])) {
  881.             $GLOBALS['cfg']['ColumnTypes'][] = 'BINARY';
  882.         }
  883.         if (!in_array('VARBINARY', $GLOBALS['cfg']['ColumnTypes'])) {
  884.             $GLOBALS['cfg']['ColumnTypes'][] = 'VARBINARY';
  885.         }
  886.     } else {
  887.         require_once './libraries/charset_conversion.lib.php';
  888.     }
  889. }
  890.  
  891. /**
  892.  * returns a single value from the given result or query,
  893.  * if the query or the result has more than one row or field
  894.  * the first field of the first row is returned
  895.  *
  896.  * <code>
  897.  * $sql = 'SELECT `name` FROM `user` WHERE `id` = 123';
  898.  * $user_name = PMA_DBI_fetch_value($sql);
  899.  * // produces
  900.  * // $user_name = 'John Doe'
  901.  * </code>
  902.  *
  903.  * @uses    is_string()
  904.  * @uses    is_int()
  905.  * @uses    PMA_DBI_try_query()
  906.  * @uses    PMA_DBI_num_rows()
  907.  * @uses    PMA_DBI_fetch_row()
  908.  * @uses    PMA_DBI_fetch_assoc()
  909.  * @uses    PMA_DBI_free_result()
  910.  * @param   string|mysql_result $result query or mysql result
  911.  * @param   integer             $row_number row to fetch the value from,
  912.  *                                      starting at 0, with 0 beeing default
  913.  * @param   integer|string      $field  field to fetch the value from,
  914.  *                                      starting at 0, with 0 beeing default
  915.  * @param   resource            $link   mysql link
  916.  * @param   mixed               $options
  917.  * @return  mixed               value of first field in first row from result
  918.  *                              or false if not found
  919.  */
  920. function PMA_DBI_fetch_value($result, $row_number = 0, $field = 0, $link = null, $options = 0) {
  921.     $value = false;
  922.  
  923.     if (is_string($result)) {
  924.         $result = PMA_DBI_try_query($result, $link, $options | PMA_DBI_QUERY_STORE);
  925.     }
  926.  
  927.     // return false if result is empty or false
  928.     // or requested row is larger than rows in result
  929.     if (PMA_DBI_num_rows($result) < ($row_number + 1)) {
  930.         return $value;
  931.     }
  932.  
  933.     // if $field is an integer use non associative mysql fetch function
  934.     if (is_int($field)) {
  935.         $fetch_function = 'PMA_DBI_fetch_row';
  936.     } else {
  937.         $fetch_function = 'PMA_DBI_fetch_assoc';
  938.     }
  939.  
  940.     // get requested row
  941.     for ($i = 0; $i <= $row_number; $i++) {
  942.         $row = $fetch_function($result);
  943.     }
  944.     PMA_DBI_free_result($result);
  945.  
  946.     // return requested field
  947.     if (isset($row[$field])) {
  948.         $value = $row[$field];
  949.     }
  950.     unset($row);
  951.  
  952.     return $value;
  953. }
  954.  
  955. /**
  956.  * returns only the first row from the result
  957.  *
  958.  * <code>
  959.  * $sql = 'SELECT * FROM `user` WHERE `id` = 123';
  960.  * $user = PMA_DBI_fetch_single_row($sql);
  961.  * // produces
  962.  * // $user = array('id' => 123, 'name' => 'John Doe')
  963.  * </code>
  964.  *
  965.  * @uses    is_string()
  966.  * @uses    PMA_DBI_try_query()
  967.  * @uses    PMA_DBI_num_rows()
  968.  * @uses    PMA_DBI_fetch_row()
  969.  * @uses    PMA_DBI_fetch_assoc()
  970.  * @uses    PMA_DBI_fetch_array()
  971.  * @uses    PMA_DBI_free_result()
  972.  * @param   string|mysql_result $result query or mysql result
  973.  * @param   string              $type   NUM|ASSOC|BOTH
  974.  *                                      returned array should either numeric
  975.  *                                      associativ or booth
  976.  * @param   resource            $link   mysql link
  977.  * @param   mixed               $options
  978.  * @return  array|boolean       first row from result
  979.  *                              or false if result is empty
  980.  */
  981. function PMA_DBI_fetch_single_row($result, $type = 'ASSOC', $link = null, $options = 0) {
  982.     if (is_string($result)) {
  983.         $result = PMA_DBI_try_query($result, $link, $options | PMA_DBI_QUERY_STORE);
  984.     }
  985.  
  986.     // return null if result is empty or false
  987.     if (! PMA_DBI_num_rows($result)) {
  988.         return false;
  989.     }
  990.  
  991.     switch ($type) {
  992.         case 'NUM' :
  993.             $fetch_function = 'PMA_DBI_fetch_row';
  994.             break;
  995.         case 'ASSOC' :
  996.             $fetch_function = 'PMA_DBI_fetch_assoc';
  997.             break;
  998.         case 'BOTH' :
  999.         default :
  1000.             $fetch_function = 'PMA_DBI_fetch_array';
  1001.             break;
  1002.     }
  1003.  
  1004.     $row = $fetch_function($result);
  1005.     PMA_DBI_free_result($result);
  1006.     return $row;
  1007. }
  1008.  
  1009. /**
  1010.  * returns all rows in the resultset in one array
  1011.  *
  1012.  * <code>
  1013.  * $sql = 'SELECT * FROM `user`';
  1014.  * $users = PMA_DBI_fetch_result($sql);
  1015.  * // produces
  1016.  * // $users[] = array('id' => 123, 'name' => 'John Doe')
  1017.  *
  1018.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1019.  * $users = PMA_DBI_fetch_result($sql, 'id');
  1020.  * // produces
  1021.  * // $users['123'] = array('id' => 123, 'name' => 'John Doe')
  1022.  *
  1023.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1024.  * $users = PMA_DBI_fetch_result($sql, 0);
  1025.  * // produces
  1026.  * // $users['123'] = array(0 => 123, 1 => 'John Doe')
  1027.  *
  1028.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1029.  * $users = PMA_DBI_fetch_result($sql, 'id', 'name');
  1030.  * // or
  1031.  * $users = PMA_DBI_fetch_result($sql, 0, 1);
  1032.  * // produces
  1033.  * // $users['123'] = 'John Doe'
  1034.  *
  1035.  * $sql = 'SELECT `name` FROM `user`';
  1036.  * $users = PMA_DBI_fetch_result($sql);
  1037.  * // produces
  1038.  * // $users[] = 'John Doe'
  1039.  * </code>
  1040.  *
  1041.  * @uses    is_string()
  1042.  * @uses    is_int()
  1043.  * @uses    PMA_DBI_try_query()
  1044.  * @uses    PMA_DBI_num_rows()
  1045.  * @uses    PMA_DBI_num_fields()
  1046.  * @uses    PMA_DBI_fetch_row()
  1047.  * @uses    PMA_DBI_fetch_assoc()
  1048.  * @uses    PMA_DBI_free_result()
  1049.  * @param   string|mysql_result $result query or mysql result
  1050.  * @param   string|integer      $key    field-name or offset
  1051.  *                                      used as key for array
  1052.  * @param   string|integer      $value  value-name or offset
  1053.  *                                      used as value for array
  1054.  * @param   resource            $link   mysql link
  1055.  * @param   mixed               $options
  1056.  * @return  array               resultrows or values indexed by $key
  1057.  */
  1058. function PMA_DBI_fetch_result($result, $key = null, $value = null,
  1059.     $link = null, $options = 0)
  1060. {
  1061.     $resultrows = array();
  1062.  
  1063.     if (is_string($result)) {
  1064.         $result = PMA_DBI_try_query($result, $link, $options);
  1065.     }
  1066.  
  1067.     // return empty array if result is empty or false
  1068.     if (! $result) {
  1069.         return $resultrows;
  1070.     }
  1071.  
  1072.     $fetch_function = 'PMA_DBI_fetch_assoc';
  1073.  
  1074.     // no nested array if only one field is in result
  1075.     if (null === $key && 1 === PMA_DBI_num_fields($result)) {
  1076.         $value = 0;
  1077.         $fetch_function = 'PMA_DBI_fetch_row';
  1078.     }
  1079.  
  1080.     // if $key is an integer use non associative mysql fetch function
  1081.     if (is_int($key)) {
  1082.         $fetch_function = 'PMA_DBI_fetch_row';
  1083.     }
  1084.  
  1085.     if (null === $key && null === $value) {
  1086.         while ($row = $fetch_function($result)) {
  1087.             $resultrows[] = $row;
  1088.         }
  1089.     } elseif (null === $key) {
  1090.         while ($row = $fetch_function($result)) {
  1091.             $resultrows[] = $row[$value];
  1092.         }
  1093.     } elseif (null === $value) {
  1094.         if (is_array($key)) {
  1095.             while ($row = $fetch_function($result)) {
  1096.                 $result_target =& $resultrows;
  1097.                 foreach ($key as $key_index) {
  1098.                     if (! isset($result_target[$row[$key_index]])) {
  1099.                         $result_target[$row[$key_index]] = array();
  1100.                     }
  1101.                     $result_target =& $result_target[$row[$key_index]];
  1102.                 }
  1103.                 $result_target = $row;
  1104.             }
  1105.         } else {
  1106.             while ($row = $fetch_function($result)) {
  1107.                 $resultrows[$row[$key]] = $row;
  1108.             }
  1109.         }
  1110.     } else {
  1111.         if (is_array($key)) {
  1112.             while ($row = $fetch_function($result)) {
  1113.                 $result_target =& $resultrows;
  1114.                 foreach ($key as $key_index) {
  1115.                     if (! isset($result_target[$row[$key_index]])) {
  1116.                         $result_target[$row[$key_index]] = array();
  1117.                     }
  1118.                     $result_target =& $result_target[$row[$key_index]];
  1119.                 }
  1120.                 $result_target = $row[$value];
  1121.             }
  1122.         } else {
  1123.             while ($row = $fetch_function($result)) {
  1124.                 $resultrows[$row[$key]] = $row[$value];
  1125.             }
  1126.         }
  1127.     }
  1128.  
  1129.     PMA_DBI_free_result($result);
  1130.     return $resultrows;
  1131. }
  1132.  
  1133. /**
  1134.  * return default table engine for given database
  1135.  *
  1136.  * @return  string  default table engine
  1137.  */
  1138. function PMA_DBI_get_default_engine()
  1139. {
  1140.     if (PMA_MYSQL_INT_VERSION > 50002) {
  1141.         return PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'storage_engine\';', 0, 1);
  1142.     } else {
  1143.         return PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'table_type\';', 0, 1);
  1144.     }
  1145. }
  1146.  
  1147. /**
  1148.  * Get supported SQL compatibility modes
  1149.  *
  1150.  * @return  array   supported SQL compatibility modes
  1151.  */
  1152. function PMA_DBI_getCompatibilities()
  1153. {
  1154.     if (PMA_MYSQL_INT_VERSION < 40100) {
  1155.         return array();
  1156.     }
  1157.     $compats = array('NONE');
  1158.     if (PMA_MYSQL_INT_VERSION >= 40101) {
  1159.         $compats[] = 'ANSI';
  1160.         $compats[] = 'DB2';
  1161.         $compats[] = 'MAXDB';
  1162.         $compats[] = 'MYSQL323';
  1163.         $compats[] = 'MYSQL40';
  1164.         $compats[] = 'MSSQL';
  1165.         $compats[] = 'ORACLE';
  1166.         // removed; in MySQL 5.0.33, this produces exports that
  1167.         // can't be read by POSTGRESQL (see our bug #1596328)
  1168.         //$compats[] = 'POSTGRESQL';
  1169.         if (PMA_MYSQL_INT_VERSION >= 50002) {
  1170.             $compats[] = 'TRADITIONAL';
  1171.         }
  1172.     }
  1173.     return $compats;
  1174. }
  1175.  
  1176. /**
  1177.  * returns warnings for last query
  1178.  *
  1179.  * @uses    $GLOBALS['userlink']
  1180.  * @uses    PMA_DBI_fetch_result()
  1181.  * @param   resource mysql link  $link   mysql link resource
  1182.  * @return  array   warnings
  1183.  */
  1184. function PMA_DBI_get_warnings($link = null)
  1185. {
  1186.     if (PMA_MYSQL_INT_VERSION < 40100) {
  1187.         return array();
  1188.     }
  1189.  
  1190.     if (empty($link)) {
  1191.         if (isset($GLOBALS['userlink'])) {
  1192.             $link = $GLOBALS['userlink'];
  1193.         } else {
  1194.             return array();
  1195.         }
  1196.     }
  1197.  
  1198.     return PMA_DBI_fetch_result('SHOW WARNINGS', null, null, $link);
  1199. }
  1200.  
  1201. /**
  1202.  * returns true (int > 0) if current user is superuser
  1203.  * otherwise 0
  1204.  *
  1205.  * @return integer  $is_superuser
  1206.  */
  1207. function PMA_isSuperuser() {
  1208.     return PMA_DBI_try_query('SELECT COUNT(*) FROM mysql.user',
  1209.         $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
  1210. }
  1211.  
  1212.  
  1213. /**
  1214.  * returns an array of PROCEDURE or FUNCTION names for a db
  1215.  *
  1216.  * @uses    PMA_DBI_free_result()
  1217.  * @param   string              $db     db name
  1218.  * @param   string              $which  PROCEDURE | FUNCTION
  1219.  * @param   resource            $link   mysql link
  1220.  *
  1221.  * @return  array   the procedure names or function names
  1222.  */
  1223. function PMA_DBI_get_procedures_or_functions($db, $which, $link = null) {
  1224.  
  1225.     $shows = PMA_DBI_fetch_result('SHOW ' . $which . ' STATUS;', null, null, $link);
  1226.     $result = array();
  1227.     foreach ($shows as $one_show) {
  1228.         if ($one_show['Db'] == $db && $one_show['Type'] == $which) {
  1229.             $result[] = $one_show['Name'];
  1230.         }
  1231.     }
  1232.     return($result);
  1233. }
  1234.  
  1235. /**
  1236.  * returns the definition of a specific PROCEDURE or FUNCTION
  1237.  *
  1238.  * @uses    PMA_DBI_fetch_value()
  1239.  * @param   string              $db     db name
  1240.  * @param   string              $which  PROCEDURE | FUNCTION
  1241.  * @param   string              $proc_or_function_name  the procedure name or function name
  1242.  * @param   resource            $link   mysql link
  1243.  *
  1244.  * @return  string              the procedure's or function's definition
  1245.  */
  1246. function PMA_DBI_get_procedure_or_function_def($db, $which, $proc_or_function_name, $link = null) {
  1247.  
  1248.     $returned_field = array('PROCEDURE' => 'Create Procedure', 'FUNCTION' => 'Create Function');
  1249.     $query = 'SHOW CREATE ' . $which . ' ' . PMA_backquote($db) . '.' . PMA_backquote($proc_or_function_name);
  1250.     return(PMA_DBI_fetch_value($query, 0, $returned_field[$which]));
  1251. }
  1252.  
  1253. /**
  1254.  * returns details about the TRIGGERs of a specific table
  1255.  *
  1256.  * @uses    PMA_DBI_fetch_result()
  1257.  * @param   string              $db     db name
  1258.  * @param   string              $table  table name
  1259.  *
  1260.  * @return  array               information about triggers (may be empty)
  1261.  */
  1262. function PMA_DBI_get_triggers($db, $table) {
  1263.  
  1264.     $result = array();
  1265.  
  1266.     // available in INFORMATION_SCHEMA since MySQL 5.0.10
  1267.     if (PMA_MYSQL_INT_VERSION >= 50010) {
  1268.         $triggers = PMA_DBI_fetch_result("SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA= '" . PMA_sqlAddslashes($db,true) . "' and EVENT_OBJECT_TABLE = '" . PMA_sqlAddslashes($table, true) . "';");
  1269.  
  1270.         if ($triggers) {
  1271.             $delimiter = '//';
  1272.             foreach ($triggers as $trigger) {
  1273.                 $one_result = array();
  1274.                 $one_result['name'] = $trigger['TRIGGER_NAME'];
  1275.                 $one_result['action_timing'] = $trigger['ACTION_TIMING'];
  1276.                 $one_result['event_manipulation'] = $trigger['EVENT_MANIPULATION'];
  1277.  
  1278.                 $one_result['full_trigger_name'] = PMA_backquote($trigger['TRIGGER_SCHEMA']) . '.' . PMA_backquote($trigger['TRIGGER_NAME']);
  1279.                 $one_result['drop'] = 'DROP TRIGGER ' . $one_result['full_trigger_name'];
  1280.                 $one_result['create'] = 'CREATE TRIGGER ' . $one_result['full_trigger_name'] . ' ' . $trigger['ACTION_TIMING']. ' ' . $trigger['EVENT_MANIPULATION'] . ' ON ' . PMA_backquote($trigger['EVENT_OBJECT_SCHEMA']) . '.' . PMA_backquote($trigger['EVENT_OBJECT_TABLE']) . "\n" . ' FOR EACH ROW ' . $trigger['ACTION_STATEMENT'] . "\n" . $delimiter . "\n";
  1281.  
  1282.                 $result[] = $one_result;
  1283.             }
  1284.         }
  1285.     }
  1286.     return($result);
  1287. }
  1288. ?>
  1289.